using CfgTable;
using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using System.Collections.Generic;

namespace IQIGame.Onigao.GamePlay
{
    public class UIN_HeroFateTrajectory : UIBaseNode
    {
        #region Template Generate,don't modify
        protected class UIB_UIN_HeroFateTrajectory
        {
            #region ObjectBinding Generate
            public UnityEngine.GameObject pointStage { protected set; get; }
            public UnityEngine.GameObject current { protected set; get; }
            public IQIGame.Onigao.Framework.ExButton btnAttribute { protected set; get; }
            public IQIGame.Onigao.Framework.ExText name { protected set; get; }
            public UnityEngine.GameObject attributeCurrent { protected set; get; }
            public UnityEngine.GameObject commonItem { protected set; get; }
            public UnityEngine.GameObject costMoney { protected set; get; }
            public IQIGame.Onigao.Framework.ExButton btnUpdate { protected set; get; }
            public UnityEngine.GameObject lockRoot { protected set; get; }
            public IQIGame.Onigao.Framework.ExText textLock { protected set; get; }
            public UnityEngine.GameObject completed { protected set; get; }
            public UnityEngine.GameObject attributeCompleted { protected set; get; }
            public UnityEngine.GameObject tipAllAttribute { protected set; get; }
            public virtual void InitBinding(ObjectBinding __binding)
            {
                __binding.TryGetVariableValue<UnityEngine.GameObject>("pointStage", out var __tbv0);
                this.pointStage = __tbv0;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("current", out var __tbv1);
                this.current = __tbv1;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExButton>("btnAttribute", out var __tbv2);
                this.btnAttribute = __tbv2;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExText>("name", out var __tbv3);
                this.name = __tbv3;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("attributeCurrent", out var __tbv4);
                this.attributeCurrent = __tbv4;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("commonItem", out var __tbv5);
                this.commonItem = __tbv5;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("costMoney", out var __tbv6);
                this.costMoney = __tbv6;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExButton>("btnUpdate", out var __tbv7);
                this.btnUpdate = __tbv7;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("lockRoot", out var __tbv8);
                this.lockRoot = __tbv8;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExText>("textLock", out var __tbv9);
                this.textLock = __tbv9;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("completed", out var __tbv10);
                this.completed = __tbv10;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("attributeCompleted", out var __tbv11);
                this.attributeCompleted = __tbv11;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("tipAllAttribute", out var __tbv12);
                this.tipAllAttribute = __tbv12;
            }
            #endregion ObjectBinding Generate 
        }
        #endregion Template Generate,don't modify

        #region fields
        private IrregularListAdapter<UIN_CommonDarkLightPreview> points;
        private ListScrollAdapter<UIN_CommonAttribute> currentAttrs = null;
        private ListScrollAdapter<UIN_CostItem> costItems = null;
        private UIN_CostMoney costMoney = null;
        private UIN_HeroFateTrajectoryTipAllAttribute tipAllAttribute = null;
        private ListScrollAdapter<UIN_CommonAttribute> completedAttrs = null;

        private HeroData heroData;
        private int currentStage = 0;
        private CfgHeroFateTrajectory cfgData = null;
        private int maxStage = 0;
        private bool isMaxStage = false;
        private IReadOnlyList<int> groupCfgCids = null;
        private Dictionary<int, int> dicAttrCid2Value = DictionaryPool<int, int>.Get();
        private List<int> listAttrCid = ListPool<int>.Get();
        #endregion fields

        #region properties

        protected UIB_UIN_HeroFateTrajectory ui { get; set; }
        protected UIMsgDispatcher uiMsgDispatcher => this._msgDispatcher as UIMsgDispatcher;

        #endregion properties

        protected override void BeforeInit()
        {
            ui = new UIB_UIN_HeroFateTrajectory();
            ui.InitBinding(this.csObjBind);
        }

        protected override void OnInit()
        {
            this.points = this.InitIrregularList<UIN_CommonDarkLightPreview>(this.ui.pointStage, this.OnPointStageChanged);

            #region current
            this.currentAttrs = this.InitListScroll<UIN_CommonAttribute>(this.ui.attributeCurrent, this.OnAttributeChanged);
            this.costItems = this.InitListScroll<UIN_CostItem>(this.ui.commonItem, this.OnCostItemChanged);
            this.costMoney = this.InitChildNode<UIN_CostMoney>(this.ui.costMoney);
            this.tipAllAttribute = this.InitChildNode<UIN_HeroFateTrajectoryTipAllAttribute>(this.ui.tipAllAttribute);
            #endregion current

            this.completedAttrs = this.InitListScroll<UIN_CommonAttribute>(this.ui.attributeCompleted, this.OnAttributeChanged);
        }

        protected override void OnShow()
        {

        }

        protected override void OnHide()
        {

        }

        /// <summary>
        /// 添加UGUI侦听
        /// </summary>
        protected override void AddUGUIListener()
        {
            this.ui.btnAttribute.onClick.AddListener(this.OnClickBtnAttribute);
            this.ui.btnUpdate.onClick.AddListener(this.OnClickBtnUpdate);
        }

        /// <summary>
        /// 添加全局侦听（MsgDispatcher）
        /// </summary>
        protected override void AddMsgListeners()
        {

        }

        protected override void OnDispose()
        {
            if (this.dicAttrCid2Value != null)
            {
                DictionaryPool<int, int>.Put(this.dicAttrCid2Value);
                this.dicAttrCid2Value = null;
            }

            if (this.listAttrCid != null)
            {
                ListPool<int>.Put(this.listAttrCid);
                this.listAttrCid = null;
            }
        }

        #region methonds

        public void Show(HeroData data)
        {
            this.Show();
            this.SetData(data);

            this.ShowPointStage();
            this.ShowCurrentStage();
            this.ShowCompletedStage();
        }

        private void SetData(HeroData data)
        {
            this.heroData = data;
            this.InitCurrent();
        }

        private void InitCurrent()
        {
            this.InitMax();

            int stage = this.heroData.fateTrajectoryStage;
            this.currentStage = this.isMaxStage ? stage : stage + 1;

            this.cfgData = TableCenter.heroFateTrajectory.GetCfg(this.heroData.cid, this.currentStage);
            this.groupCfgCids = TableCenter.heroFateTrajectory.GetCids(this.heroData.cid, this.cfgData.GroupId);

            this.InitShowAttrs();
        }

        private void InitMax()
        {
            this.maxStage = TableCenter.heroFateTrajectory.MaxStage(this.heroData.cid);
            this.isMaxStage = this.maxStage == this.heroData.fateTrajectoryStage;
        }

        private void InitShowAttrs()
        {
            this.dicAttrCid2Value.Clear();
            this.listAttrCid.Clear();

            if (this.isMaxStage)
            {
                for (int i = 1; i < this.currentStage; i++)
                {
                    var cfg = TableCenter.heroFateTrajectory.GetCfg(this.heroData.cid, i);
                    this.InitShowAttrInDictionary(cfg);
                }
            }
            this.InitShowAttrInDictionary(this.cfgData);

            this.listAttrCid.AddRange(this.dicAttrCid2Value.Keys);
        }

        private void InitShowAttrInDictionary(CfgHeroFateTrajectory cfg)
        {
            if (cfg == null)
                return;
            for (var i = 0; i < cfg.AttType.Count; i++)
            {
                int cid = cfg.AttType[i];
                int val = cfg.AttValue[i];

                this.dicAttrCid2Value.TryGetValue(cid, out var count);
                count += val;
                this.dicAttrCid2Value[cid] = count;
            }
        }

        private void ShowPointStage()
        {
            int cnt = this.groupCfgCids.Count;
            this.points.RefillCells(cnt);
        }

        private void OnPointStageChanged(UIN_CommonDarkLightPreview item, int index)
        {
            int stage = index + 1;
            int state = this.GetStageState(stage);
            item.Show(state);
        }

        private int GetStageState(int stage)
        {
            if (this.isMaxStage)
                return 1;

            int cid = this.groupCfgCids[0];
            var cfg = TableCenter.heroFateTrajectory.Get(cid);
            int currStage = this.currentStage - cfg.Stage + 1;
            int state = (currStage > stage) ? 1 : (currStage == stage) ? 2 : 0;
            return state;
        }

        private void ShowCurrentStage()
        {
            bool isActive = !this.isMaxStage;
            if (isActive)
            {
                this.ShowCurrentName();
                this.ShowCurrentAttribute();
                this.ShowCurrentCostItems();
                this.ShowCurrentCostMoney();
                this.ShowCurrentBtnAndLimitInfo();
            }
            this.ui.current.SetActive(isActive);
        }

        private void ShowCurrentName()
        {
            this.ui.name.text = this.cfgData.Name;
        }

        private void ShowCurrentAttribute()
        {
            this.ShowAttribute(this.currentAttrs);
        }

        private void ShowAttribute(ListScrollAdapter<UIN_CommonAttribute> attrs)
        {
            int cnt = this.listAttrCid.Count;
            attrs.RefillCells(cnt);
        }

        private void OnAttributeChanged(UIN_CommonAttribute item, int index)
        {
            int attrCid = this.listAttrCid[index];
            int attrVal = this.dicAttrCid2Value[attrCid];
            item.ShowWhite(attrCid, attrVal);
        }

        private void ShowCurrentCostItems()
        {
            int cnt = this.cfgData.Cost.Count / APIUIConst.CostDefaultSpacing;
            this.costItems.RefillCells(cnt);
        }

        private void OnCostItemChanged(UIN_CostItem item, int index)
        {
            int kStart = index * APIUIConst.CostDefaultSpacing;
            int itemCid = this.cfgData.Cost[kStart];
            int itemNum = this.cfgData.Cost[kStart + 1];
            item.Show(itemCid, itemNum);
        }

        private void ShowCurrentCostMoney()
        {
            if (this.cfgData.GoldCost.Count == 2)
            {
                int itemCid = this.cfgData.GoldCost[0];
                int numCost = this.cfgData.GoldCost[1];
                this.costMoney.Show(itemCid, numCost);
            }
            else
            {
                this.costMoney.Hide();
            }
        }

        private void ShowCurrentBtnAndLimitInfo()
        {
            int needHeroLevel = this.cfgData.NeedHeroLevel;
            bool isLock = needHeroLevel > this.heroData.level;
            if (isLock)
            {
                this.ui.textLock.text = APIUIHeroInfo.GetHeroFateTrajectoryStageUnlockStr(needHeroLevel);
            }
            this.ui.lockRoot.SetActive(isLock);
            this.ui.btnUpdate.SetActive(!isLock);

            bool isActiveAttr = this.heroData.fateTrajectoryStage > 0 && !this.isMaxStage;
            this.ui.btnAttribute.SetActive(isActiveAttr);
        }

        private void OnClickBtnUpdate()
        {
            this.SendUpdateStage().Forget();
        }

        private async UniTaskVoid SendUpdateStage()
        {
            var result = await HeroModule.NetCore.CS_upFateTrajectory(this.heroData.cid);
            if (result.IsSuccess)
            {
                HeroModule.Instance.UpHeroByPOD(result.heroPOD);
                this.RefreshUpdateStageSuccess();
            }
        }

        private void RefreshUpdateStageSuccess()
        {
            this.InitCurrent();
            this.ShowPointStage();
            this.ShowCurrentStage();
            this.ShowCompletedStage();
        }

        private void OnClickBtnAttribute()
        {
            this.ShowTipAllAttribute();
        }

        private void ShowTipAllAttribute()
        {
            this.tipAllAttribute.Show(this.heroData);
        }

        private void ShowCompletedStage()
        {
            bool isActive = this.isMaxStage;
            if (isActive)
            {
                this.ShowCompletedAttribute();
            }
            this.ui.completed.SetActive(isActive);
        }

        private void ShowCompletedAttribute()
        {
            this.ShowAttribute(this.completedAttrs);
        }
        #endregion methonds
    }
}
